﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NET.MidTestRework.Lib.Interface;
using System.Text.RegularExpressions;
using NET.MidTestRework.Lib.Exception;

namespace NET.MidTestRework.Lib
{
    public class Cryptography : ICryptography
    {
        private static char[] base26Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
        private static char[] base10Chars = "1234567890".ToCharArray();
        private static int[] validStepValue = { 1, 2, 3, 4, 5 };

        public string Encrypt(string input, int stepPerformed)
        {
            string result = null;
            if (IsAlphanumeric(input) && !input.Equals(""))
            {
                if (IsValidStepValue(stepPerformed) && !input.Equals(""))
                {
                    StringBuilder sb = new StringBuilder(input);                   
                    for (int i = 0; i < input.Length; i++)
                    {
                        sb[i] = FindChar(stepPerformed, sb[i], 'A');
                    }
                    result = sb.ToString();
                    return result;
                }
                else
                {
                    throw new InvalidStepformedException("Invalid Stepformed Input");
                }
            }
            else
            {
                throw new InvalidAlphanumericException();
            }
        }

        public string Decrypt(string input, int stepPerformed)
        {
            string result = null;
            if (IsAlphanumeric(input) && !input.Equals(""))
            {
                if (IsValidStepValue(stepPerformed) && !input.Equals(""))
                {
                    StringBuilder sb = new StringBuilder(input);
                    for (int i = 0; i < input.Length; i++)
                    {
                        sb[i] = FindChar(stepPerformed, sb[i], 'S');
                    }
                    result = sb.ToString();
                    return result;
                }
                else
                {
                    throw new InvalidStepformedException("Invalid Stepformed Input");
                }
            }
            else
            {
                throw new InvalidAlphanumericException();
            }
        }

        public bool IsAlphanumeric(string input)
        {
            Regex r = new Regex("^[a-zA-Z0-9]*$");
            if (r.IsMatch(input) && !input.Equals(""))
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        public char FindChar(int index, char input, char Operator)
        {
            int findIndexBase26Char = Array.IndexOf(base26Chars, input);
            int findIndexBase10Char = Array.IndexOf(base10Chars, input);
            switch (Operator)
            {
                case 'A':
                    if (IsBase26Char(input))
                    {
                        input = base26Chars[(findIndexBase26Char + index) % 26];
                    }
                    else
                    {
                        input = base10Chars[(findIndexBase10Char + index) % 10];
                    }                  
                    break;
                case 'S':
                    if (IsBase26Char(input))
                    {
                        input = base26Chars[(26 + (findIndexBase26Char - index)) % 26];
                    }
                    else
                    {
                        input = base10Chars[(10 + (findIndexBase10Char - index)) % 10];
                    }                  
                    break;
                default:
                    break;
            }
            return input;
        }

        public bool IsValidStepValue(int stepPerformed)
        {
            if (validStepValue.Contains(stepPerformed))
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        public bool IsBase26Char(char input)
        {
            if (base26Chars.Contains(input))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
